﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Modbus_TCP
{
    public partial class Form1 : Form
    {
        public class StateObject
        {
            // Client socket.     
            public Socket workSocket = null;
            // Size of receive buffer.     
            public const int BufferSize = 1024;
            // Receive buffer.     
            public byte[] buffer = new byte[BufferSize];
            public int num;
        }

        List<Socket> listClient1 = new List<Socket>();
        List<Socket> listClient2 = new List<Socket>();
        List<Socket> listClient3 = new List<Socket>();
        List<Socket> listClient4 = new List<Socket>();
        List<Socket> listClient5 = new List<Socket>();
        List<Socket> listClient6 = new List<Socket>();
        List<Socket> listClient7 = new List<Socket>();
        List<Socket> listClient8 = new List<Socket>();

        String content = String.Empty;

        public Form1()
        {
            InitializeComponent();

            string name = Dns.GetHostName();
            IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
            foreach (IPAddress ipa in ipadrlist)
            {
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                {
                    ServerIP1.Text = ipa.ToString();
                    ServerIP2.Text = ipa.ToString();
                    ServerIP3.Text = ipa.ToString();
                    ServerIP4.Text = ipa.ToString();
                    ServerIP5.Text = ipa.ToString();
                    ServerIP6.Text = ipa.ToString();
                    ServerIP7.Text = ipa.ToString();
                    ServerIP8.Text = ipa.ToString();

                    ClientIP1.Text = ipa.ToString();
                    ClientIP2.Text = ipa.ToString();
                    ClientIP3.Text = ipa.ToString();
                    ClientIP4.Text = ipa.ToString();
                    ClientIP5.Text = ipa.ToString();
                    ClientIP6.Text = ipa.ToString();
                    ClientIP7.Text = ipa.ToString();
                    ClientIP8.Text = ipa.ToString();
                    break;
                }
            }
        }

        /// <summary>
        /// 更新界面状态信息委托回调事件
        /// </summary>
        /// <param name="str"></param>
        public delegate void ShowStatusCallBack(String str);
        /// <summary>
        /// 更新界面状态信息
        /// </summary>
        /// <param name="str"></param>
        public void ShowStatus(string str)
        {
            if (this.InvokeRequired)
            {
                ShowStatusCallBack d = new ShowStatusCallBack(ShowStatus);
                this.Invoke(d, new object[] { str });
            }
            else
            {
                textBoxMessage.Text += str + "\r\n";
                textBoxMessage.SelectionStart = textBoxMessage.Text.Length;
                textBoxMessage.ScrollToCaret();

                if(textBoxMessage.Text.Length > 10000)
                {
                    textBoxMessage.Clear();
                }
            }
        }

        public void StartServer(int num, string ip, string port)
        {
            IPAddress address = IPAddress.Parse(ip.Trim());
            int portNum = int.Parse(port.Trim());
            IPEndPoint endPoint = new IPEndPoint(address, portNum);

            try
            {
                // 创建负责监听的套接字，注意其中的参数；  
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                listener.Bind(endPoint);
                // 设置监听队列的长度；  
                listener.Listen(10);

                StateObject stateObject = new StateObject();
                stateObject.workSocket = listener;
                stateObject.num = num;
                // Set the event to nonsignaled state.     
                listener.BeginAccept(new AsyncCallback(AcceptCallback), stateObject);

                textBoxMessage.Text += "服务器" + num.ToString() + "已开启，等待连接。。。。。\r\n";

            }
            catch (Exception ex)
            {
                ShowStatus(ex.Message);
            }

        }

        public void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket.EndAccept(ar);

                IPEndPoint remoteEndPoint;
                remoteEndPoint = (IPEndPoint)client.RemoteEndPoint;

                ShowStatus("客户端已连接！" + remoteEndPoint.Address.ToString() + ":" + remoteEndPoint.Port.ToString());

                StateObject clientState = new StateObject();
                clientState.num = state.num;
                clientState.workSocket = client;

                client.BeginReceive(clientState.buffer, 0, clientState.buffer.Length, 0, new AsyncCallback(ReadCallback), clientState);

                switch (state.num)
                {
                    case 1:
                        listClient1.Add(client);
                        break;
                    case 2:
                        listClient2.Add(client);
                        break;
                    case 3:
                        listClient3.Add(client);
                        break;
                    case 4:
                        listClient4.Add(client);
                        break;
                    case 5:
                        listClient5.Add(client);
                        break;
                    case 6:
                        listClient6.Add(client);
                        break;
                    case 7:
                        listClient7.Add(client);
                        break;
                    case 8:
                        listClient8.Add(client);
                        break;
                }

                state.workSocket.BeginAccept(new AsyncCallback(AcceptCallback), state);
            }
            catch (Exception ex)
            {
                ShowStatus(ex.Message);
            }
        }

        public void ReadCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = (StateObject)ar.AsyncState;

                // Read data from the client socket.     
                int bytesRead = state.workSocket.EndReceive(ar);
                if (bytesRead > 0)
                {
                    // more data.     
                    //content = Encoding.ASCII.GetString(bufferData_Server, 0, bytesRead);

                    content = ByteToString(state.buffer, bytesRead);
                    ShowStatus("服务器--" + state.num + "-- " + content);
                    //转发
                    Send(state, bytesRead);

                    Array.Clear(state.buffer, 0, state.buffer.Length);

                    state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length, 0, new AsyncCallback(ReadCallback), state);


                    //if (bytesRead == 97 && bufferData_Server[0] == 0xCF)
                    //{
                    //    //content = Encoding.ASCII.GetString(bufferData_Server, 0, bytesRead);
                    //    content = ByteToString(bufferData_Server, bytesRead);
                    //    ShowStatus("服务器接收：" + content);

                    //    client.BeginReceive(bufferData_Server, 0, bufferData_Server.Length, 0, new AsyncCallback(ReadCallback), client);
                    //    Array.Clear(bufferData_Server, 0, bufferData_Server.Length);
                    //}
                    //else
                    //{
                    //    // Not all data received. Get more.     
                    //    client.BeginReceive(bufferData_Server, 0, bufferData_Server.Length, 0, new AsyncCallback(ReadCallback), client);
                    //    Array.Clear(bufferData_Server, 0, bufferData_Server.Length);
                    //}
                }

            } catch (Exception ex)
            {
                ShowStatus(ex.Message);
            }
        }

        private void Send(StateObject stateObject, int byteRead)
        {
            try
            {
                //string text = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
                //ShowStatus("发送数据：" + text);
                //if (null != SocketClient)
                //{
                //    SocketClient.BeginSend(buffer, 0, buffer.Length, 0, new AsyncCallback(SendCallback), SocketClient);
                //}

                switch (stateObject.num)
                {
                    case 1:
                        if(null != listClient1 && listClient1.Count > 0)
                        {
                            foreach(Socket socket in listClient1)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 2:
                        if (null != listClient2 && listClient2.Count > 0)
                        {
                            foreach (Socket socket in listClient2)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 3:
                        if (null != listClient3 && listClient3.Count > 0)
                        {
                            foreach (Socket socket in listClient3)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 4:
                        if (null != listClient4 && listClient4.Count > 0)
                        {
                            foreach (Socket socket in listClient4)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 5:
                        if (null != listClient5 && listClient5.Count > 0)
                        {
                            foreach (Socket socket in listClient5)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 6:
                        if (null != listClient6 && listClient6.Count > 0)
                        {
                            foreach (Socket socket in listClient6)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 7:
                        if (null != listClient7 && listClient7.Count > 0)
                        {
                            foreach (Socket socket in listClient7)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                    case 8:
                        if (null != listClient8 && listClient8.Count > 0)
                        {
                            foreach (Socket socket in listClient8)
                            {
                                socket.BeginSend(stateObject.buffer, 0, byteRead, 0, new AsyncCallback(SendCallback), socket);
                            }
                        }
                        break;
                }

            } catch (Exception ex)
            {
                ShowStatus(ex.Message);
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.     
                Socket handler = (Socket)ar.AsyncState;
                // Complete sending the data to the remote device.     
                int bytesSent = handler.EndSend(ar);
                //ShowStatus("已发送数据大小：" + bytesSent.ToString());
                //handler.Shutdown(SocketShutdown.Both);
                //handler.Close();
            }
            catch (Exception e)
            {
                ShowStatus(e.Message);
            }
        }

        public void ConnectServer(int num, string ip,string port)
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse(ip);
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, int.Parse(port));
                // Create a TCP/IP socket.     
                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                StateObject stateObject = new StateObject();
                stateObject.num = num;
                stateObject.workSocket = socketClient;

                // Connect to the remote endpoint.     
                socketClient.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), stateObject);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                StateObject stateObject = (StateObject)ar.AsyncState;
                // Retrieve the socket from the state object.     
                //Socket client = (Socket)ar.AsyncState;
                // Complete the connection.     
                stateObject.workSocket.EndConnect(ar);
                ShowStatus("已连接服务器。。。。\r\n");
                stateObject.workSocket.BeginReceive(stateObject.buffer, 0, stateObject.buffer.Length, 0, new AsyncCallback(ReadCallback), stateObject);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        /// <summary>
        /// 字节数组转为字符串，使用空格分隔
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ByteToString(byte[] bytes,int bytesRead)
        {
            string str = ByteToHexStr(bytes, bytesRead);
            string data = "";
            for (int i = 0; i < str.Length - 1; i += 2)
            {
                data += str[i].ToString() + str[i + 1].ToString() + " ";
            }
            return data;
        }

        /// <summary> 
        /// 字节数组转16进制字符串 
        /// </summary> 
        /// <param name="bytes"></param> 
        /// <returns></returns> 
        public static string ByteToHexStr(byte[] bytes,int bytesRead)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytesRead; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }

        private void BtnServer1_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            switch (btn.Name)
            {
                case "BtnServer1":
                    StartServer(1, ServerIP1.Text, ServerPort1.Text);
                    BtnServer1.Enabled = false;
                    break;
                case "BtnServer2":
                    StartServer(2, ServerIP2.Text, ServerPort2.Text);
                    BtnServer2.Enabled = false;
                    break;
                case "BtnServer3":
                    StartServer(3, ServerIP3.Text, ServerPort3.Text);
                    BtnServer3.Enabled = false;
                    break;
                case "BtnServer4":
                    StartServer(4, ServerIP4.Text, ServerPort4.Text);
                    BtnServer4.Enabled = false;
                    break;
                case "BtnServer5":
                    StartServer(5, ServerIP5.Text, ServerPort5.Text);
                    BtnServer5.Enabled = false;
                    break;
                case "BtnServer6":
                    StartServer(6, ServerIP6.Text, ServerPort6.Text);
                    BtnServer6.Enabled = false;
                    break;
                case "BtnServer7":
                    StartServer(7, ServerIP7.Text, ServerPort7.Text);
                    BtnServer7.Enabled = false;
                    break;
                case "BtnServer8":
                    StartServer(8, ServerIP8.Text, ServerPort8.Text);
                    BtnServer8.Enabled = false;
                    break;
            }
            
        }

        private void BtnConnect1_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            switch (btn.Name)
            {
                case "BtnConnect1":
                    ConnectServer(1, ClientIP1.Text, ClientPort1.Text);
                    BtnConnect1.Enabled = false;
                    break;
                case "BtnConnect2":
                    ConnectServer(2, ClientIP2.Text, ClientPort2.Text);
                    BtnConnect2.Enabled = false;
                    break;
                case "BtnConnect3":
                    ConnectServer(3, ClientIP3.Text, ClientPort3.Text);
                    BtnConnect3.Enabled = false;
                    break;
                case "BtnConnect4":
                    ConnectServer(4, ClientIP4.Text, ClientPort4.Text);
                    BtnConnect4.Enabled = false;
                    break;
                case "BtnConnect5":
                    ConnectServer(5, ClientIP5.Text, ClientPort5.Text);
                    BtnConnect5.Enabled = false;
                    break;
                case "BtnConnect6":
                    ConnectServer(6, ClientIP6.Text, ClientPort6.Text);
                    BtnConnect6.Enabled = false;
                    break;
                case "BtnConnect7":
                    ConnectServer(7, ClientIP7.Text, ClientPort7.Text);
                    BtnConnect7.Enabled = false;
                    break;
                case "BtnConnect8":
                    ConnectServer(8, ClientIP8.Text, ClientPort8.Text);
                    BtnConnect8.Enabled = false;
                    break;
            }
        }
    }
}
